package com.protocol;

import com.to.LoginReqTo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;

import java.nio.charset.StandardCharsets;
import java.util.List;

import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;

/**
 * 做 byteBuf 和 Message 之间的编解码器
 *
 * @author 罗俊华
 * @date 2021/8/27 - 3:20 下午
 */
// ByteToMessageCodec 的构造器明确标注了不允许子类使用 @Sharable 注解
//@ChannelHandler.Sharable
public class MessageCodec extends ByteToMessageCodec<Message> {

    public static final byte[] Magic_Number = new byte[]{1, 2, 3, 4};

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {

//        new WebSocketServerCompressionHandler();
//      1、协议的魔数 （4个字节）

        out.writeBytes(Magic_Number);
//      2、协议的版本号
        out.writeByte(1);
//      3、协议的序列化算法。0:json、1:jdk
        out.writeByte(0);
//      4、协议的类型
        out.writeByte(msg.getMessageType());
//      5、请求序号  （4个字节）
        out.writeInt(msg.getSequenceId());
//      6、内容长度   （4个字节）
        byte[] bytes = new ObjectMapper().writeValueAsBytes(msg);
        out.writeInt(bytes.length);
//      7、具体消息内容
        out.writeBytes(bytes);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

//      1、协议的魔数 （4个字节）
        ByteBuf byteBuf = in.readBytes(4);

        for (int i = 0; i < Magic_Number.length; i++) {
            if (byteBuf.getByte(i) != Magic_Number[i]) {
                throw new IllegalArgumentException("该协议不符合");
            }
        }
//      2、协议的版本号
        byte version = in.readByte();

        //      3、协议的序列化算法。0:json、1:jdk
        byte SerializationAlgorithm = in.readByte();

//      4、协议的类型
        byte messageType = in.readByte();
//      5、请求序号  （4个字节）
        ByteBuf sequenceId = in.readBytes(4);
//      6、内容长度   （4个字节）
        int length = in.readInt();

        byte[] content = new byte[length];
//      7、具体消息内容
        in.readBytes(content);


        ObjectMapper objectMapper = new ObjectMapper();

//        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        LoginReqTo message = objectMapper.readValue(new String(content, StandardCharsets.UTF_8), LoginReqTo.class);


        out.add(message);
    }
}
